/*
 * Copyright 2008 Daniel Freitas
 *
 * This file is part of Army Creator.
 * 
 * Army Creator is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Army Creator is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Army Creator.  If not, see <http://www.gnu.org/licenses/>.
 */
package cheesr.util;

import java.lang.reflect.InvocationTargetException;
import java.util.Comparator;

import org.apache.commons.beanutils.PropertyUtils;

public class PropertyComparator<T> implements Comparator<T> {

    private String sortByProperty;
    private SortOrder order;

    public PropertyComparator(String sortByProperty, SortOrder order) {
        this.sortByProperty = sortByProperty;
        this.order = order;
    }

    @Override
    @SuppressWarnings("unchecked")
    public int compare(T o1, T o2) {
        try {
            Object property1 = PropertyUtils.getProperty(o1, sortByProperty);
            Object property2 = PropertyUtils.getProperty(o2, sortByProperty);

            if (property1 == null) {
                return -1;
            }

            if (property2 == null) {
                return 1;
            }

            if (property1 instanceof Comparable == false || property2 instanceof Comparable == false) {
                throw new ClassCastException("Property " + sortByProperty + " of object " + o1.getClass().getName()
                        + " does not implement comparable, thus it cannot be sorted.");
            }

            Comparable typedProperty1 = (Comparable) property1;
            Comparable typedProperty2 = (Comparable) property2;

            if (order == SortOrder.ASCENDING) {
                return typedProperty1.compareTo(typedProperty2);
            }

            return typedProperty1.compareTo(typedProperty2) * -1;
        } catch (IllegalAccessException e) {
            throw new IllegalArgumentException("The property " + sortByProperty + " of object "
                    + o1.getClass().getName() + " could not be accessed.", e);
        } catch (InvocationTargetException e) {
            throw new IllegalArgumentException("The property " + sortByProperty + " of object "
                    + o1.getClass().getName() + " could not be accessed.", e);
        } catch (NoSuchMethodException e) {
            throw new IllegalArgumentException("The property " + sortByProperty + " of object "
                    + o1.getClass().getName() + " could not be accessed.", e);
        }
    }
}
